
<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>todoList</title>
    <link rel="stylesheet" href="../lib/css/todoList.css">
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        ul {
            list-style: none;
        }
    </style>
</head>

<body>
    <header>
        <div class="center">
            <span>ToDoList</span>
            <input type="text" placeholder="请输入todo" id="ipt">
        </div>
    </header>
    <div class="center todoContainer">
        <h2>正在进行 <span class="todoCount">0</span></h2>
        <ul class="todo">
            <!-- <li>
                <input type="checkbox">
                <p>内容</p>
                <input class="text" type="text">
                <span>-</span>
            </li> -->
        </ul>

        <h2>已经完成 <span class="doneCount">0</span></h2>
        <ul class="done">
            <!-- <li>
                <input type="checkbox" checked>
                <p>内容</p>
                <span>-</span>
            </li> -->
        </ul>
    </div>

    <footer>
        Copyright &copy; 2014 todolist.cn <a href="javascript:clear();">clear</a>
    </footer>

    <script src="../lib/jquery/jquery.min.js"></script>
    <script>
        /*
        页面功能：
            1. 添加 todo 事项 -> 往 todoUl 中添加 li，本地记录
            2. 删除 todo 事项 -> 去除对应 li 内容，本地记录
            3. 修改 todo 事项 -> 更改 li 内部 p 标签的内容（将 p 标签改成 input，再更换回来），本地记录
            4. 切换 todo 事项状态 -> 更改成 已完成/未完成，切换 li 中 checkbox 的选中状态，本地记录
            4. 清空页面内容 -> 删除页面上所有 li，本地记录

            简化的方案：
                添加/修改/删除/切换状态 -> 不做本地存储操作
                    -> 用数组标识之后，将数据增删改改为对数组的操作，根据数组渲染页面
                离开页面时 存储数据

        进入页面，获取本地数据，渲染 => todoLs : [ { content: xxx, done: true/false }, ... ]
            遍历本地存储的数组，生成 li，对应状态添加到 ul 元素中
        */

        // 获取本地存储的数据
        var todoLs = localStorage.getItem("todoLs"), // null  JSON字符串
            $todo = $(".todo"),
            $done = $(".done"),
            $todoContainer = $(".todoContainer"),
            dragIndex = "";

        if(todoLs){
            // 本地有数据  将字符串 -> 数组
            todoLs = JSON.parse(todoLs);
            // 根据数组渲染页面 -> 
            render();
        }else {
            // 本地没有数据，初始化为数组
            todoLs = [];
        }


        // 添加 todo
        $("#ipt").on("change", function (){
            todoLs.push({
                content: this.value,
                done: false
            })

            this.value = "";
            // 根据数组渲染页面
            render();
        })

        // 切换状态
        function changeDone(index){
            // 更改对应下标的todo对象的状态
            todoLs[index].done = event.target.checked;
            // 渲染
            render();
        }

        // 事件委托方式 -> 删除功能
        $todoContainer.on("click", "span", function (){
            // this.dataset.index  数组有的方法不更改原数组
            todoLs.splice(this.dataset.index, 1);
            // 渲染
            render();
        })

        // 清空
        function clear(){
            todoLs = [];
            render();
        }

        // 更改todo项使用 编辑模式，阻止回车事件，让其变成失去焦点。失去焦点保存信息更改todoLs 数组对应内容
        $todoContainer.on("click", "p", function (){
            // 点击添加可编辑属性，防止与拖拽冲突
            $(this).attr("contentEditable", true);
            this.focus();
        })
        $todoContainer.on("keydown", "p", function (){
            // console.log(event.key);
            if(event.key == "Enter"){
                // 阻止默认
                event.preventDefault();
                // 让元素失去焦点
                this.blur();
            }
        })

        // 编辑完成，保存到todo
        function save(index){
            todoLs[index].content = event.target.innerText;
            // 删除可编辑属性
            $(event.target).removeAttr("contentEditable");
        }

        // 拖拽交换位置
        $(".todoContainer").on("dragstart", "li", function (){
            // console.log("拖拽元素的", this.dataset.index);
            dragIndex = this.dataset.index;
            // 拖拽传值
            // event.dataTransfer.setData("index", this.dataset.index);
        })

        $(".todoContainer").on("dragover", "li", function (){
            // 阻止默认，让 drop 事件可以执行
            // 判断当前拖拽元素是否 自己或者 是否已完成的状态
            if(dragIndex !== this.dataset.index && this.parentNode !== $done[0]){
                event.preventDefault();
            }
        })

        $(".todoContainer").on("drop", "li", function (){
            // console.log("目标元素的", this.dataset.index);
            // console.log("传来的下标", event.dataTransfer.getData("index"));
            // 拖拽元素的内容
            var temp = todoLs[dragIndex].content;
            todoLs[dragIndex].content = todoLs[this.dataset.index].content;
            todoLs[this.dataset.index].content = temp;

            render();
        })


        // 渲染
        function render(){
            // 清空之前存在的内容
            $todo.html("");
            $done.html("");

            for(var i = 0; i < todoLs.length; i ++){
                // 判断状态，添加到对应 ul 中
                if(todoLs[i].done){
                    // done
                    $done.append(`<li draggable="true" data-index="${i}">
                        <input type="checkbox" checked onchange="changeDone(${i})">
                        <p onblur="save(${i})">${ todoLs[i].content }</p>
                        <span data-index="${i}">-</span>
                    </li>`);
                }else {
                    // todo
                    $todo.append(`<li draggable="true" data-index="${i}">
                        <input type="checkbox" onchange="changeDone(${i})">
                        <p onblur="save(${i})">${ todoLs[i].content }</p>
                        <span data-index="${i}">-</span>
                    </li>`);
                }
            }

            // 更改对应数量
            $(".todoCount").text($todo.children().length);
            $(".doneCount").text($done.children().length);
        }


        // 离开页面的事件
        window.onbeforeunload = function (){
            // 存储本地数据
            localStorage.setItem("todoLs", JSON.stringify(todoLs));
        }

    </script>
</body>

</html>